// HSS.Forms.Docking.DockContentHandler.cs
// ----------------------------------------------------------------------------
// Licensed under the MIT license
// http://www.opensource.org/licenses/mit-license.html
// ----------------------------------------------------------------------------
// HighSpeed-Solutions, LLC
// Copyright (c) 2001-2010
// ----------------------------------------------------------------------------
// File:       DockContentHandler.cs
// Author:     HSS\gbanta
// Created:    08/12/2010
// Modified:   12/04/2010
// ----------------------------------------------------------------------------
using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Windows.Forms;

namespace HSS.Forms.Docking
{
	/// <summary>
	/// Callback
	/// </summary>
	/// <returns></returns>
	public delegate string GetPersistStringCallback();

	/// <summary>
	/// DockContentHandler
	/// </summary>
	public class DockContentHandler : IDisposable, IDockDragSource
	{
		#region Events
		private static readonly object DockStateChangedEvent = new object();
		/// <summary>
		/// DockStateChanged
		/// </summary>
		public event EventHandler DockStateChanged
		{
			add { Events.AddHandler(DockStateChangedEvent, value); }
			remove { Events.RemoveHandler(DockStateChangedEvent, value); }
		}
		/// <summary>
		/// OnDockStateChanged
		/// </summary>
		/// <param name="e">EventArgs</param>
		protected virtual void OnDockStateChanged(EventArgs e)
		{
			EventHandler handler = (EventHandler)Events[DockStateChangedEvent];
			if (handler != null)
				handler(this, e);
		}
		#endregion
		
		/// <summary>
		/// ctor
		/// </summary>
		/// <param name="form"></param>
		public DockContentHandler(Form form)
			: this(form, null)
		{
		}

		/// <summary>
		/// ctor
		/// </summary>
		/// <param name="form"></param>
		/// <param name="getPersistStringCallback"></param>
		public DockContentHandler(Form form, GetPersistStringCallback getPersistStringCallback)
		{
			if (!(form is IDockContent))
				throw new ArgumentException(Strings.DockContent_Constructor_InvalidForm, "form");

			_form = form;
			_getPersistStringCallback = getPersistStringCallback;

			_events = new EventHandlerList();
			Form.Disposed += new EventHandler(For_Disposed);
			Form.TextChanged += new EventHandler(For_TextChanged);
		}
		
		/// <summary>
		/// Cleanup
		/// </summary>
		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="disposing"></param>
		protected virtual void Dispose(bool disposing)
		{
			if (disposing)
			{
				lock (this)
				{
					DockPanel = null;
					if (_autoHideTab != null)
						_autoHideTab.Dispose();
					if (_tab != null)
						_tab.Dispose();

					Form.Disposed -= new EventHandler(For_Disposed);
					Form.TextChanged -= new EventHandler(For_TextChanged);
					_events.Dispose();
				}
			}
		}

		/// <summary>
		/// Owning form
		/// </summary>
		public Form Form
		{
			get { return _form; }
		} Form _form;

		/// <summary>
		/// The Form as IDockContent
		/// </summary>
		public IDockContent Content
		{
			get { return Form as IDockContent; }
		}

		/// <summary>
		/// Previous Content
		/// </summary>
		public IDockContent PreviousActive
		{
			get { return _previousActive; }
			internal set { _previousActive = value; }
		} IDockContent _previousActive = null;

		/// <summary>
		/// Next Content
		/// </summary>
		public IDockContent NextActive
		{
			get { return _nextActive; }
			internal set { _nextActive = value; }
		} IDockContent _nextActive = null;

		/// <summary>
		/// Allow EndUser Docking
		/// </summary>
		public bool AllowEndUserDocking
		{
			get { return _allowEndUserDocking; }
			set { _allowEndUserDocking = value; }
		} bool _allowEndUserDocking = true;

		/// <summary>
		/// AutoHidePortion
		/// </summary>
		public double AutoHidePortion
		{
			get { return _autoHidePortion; }
			set
			{
				if (value <= 0)
					throw (new ArgumentOutOfRangeException(Strings.DockContentHandler_AutoHidePortion_OutOfRange));

				if (_autoHidePortion == value)
					return;

				_autoHidePortion = value;

				if (DockPanel == null)
					return;

				if (DockPanel.ActiveAutoHideContent == Content)
					DockPanel.PerformLayout();
			}
		} double _autoHidePortion = 0.25;

		/// <summary>
		/// Close Button
		/// </summary>
		public bool CloseButton
		{
			get { return _closeButton; }
			set
			{
				if (_closeButton == value)
					return;

				_closeButton = value;
				if (Pane != null)
					if (Pane.ActiveContent.DockHandler == this)
						Pane.RefreshChanges();
			}
		} bool _closeButton = true;

		/// <summary>
		/// DockAreas
		/// </summary>
		public DockAreas DockAreas
		{
			get { return _allowedAreas; }
			set
			{
				if (_allowedAreas == value)
					return;

				if (!DockHelper.IsDockStateValid(DockState, value))
					throw (new InvalidOperationException(Strings.DockContentHandler_DockAreas_InvalidValue));

				_allowedAreas = value;

				if (!DockHelper.IsDockStateValid(ShowHint, _allowedAreas))
					ShowHint = DockState.Unknown;
			}
		} DockAreas _allowedAreas = DockAreas.DockLeft | DockAreas.DockRight | DockAreas.DockTop | DockAreas.DockBottom | DockAreas.Document | DockAreas.Float;

		/// <summary>
		/// DockState
		/// </summary>
		public DockState DockState
		{
			get { return _dockState; }
			set
			{
				if (_dockState == value)
					return;

				DockPanel.SuspendLayout(true);

				if (value == DockState.Hidden)
					IsHidden = true;
				else
					SetDockState(false, value, Pane);

				DockPanel.ResumeLayout(true, true);
			}
		} DockState _dockState = DockState.Unknown;

		/// <summary>
		/// DockPanel
		/// </summary>
		public DockPanel DockPanel
		{
			get { return _dockPanel; }
			set
			{
				if (_dockPanel == value)
					return;

				Pane = null;

				if (_dockPanel != null)
					_dockPanel.RemoveContent(Content);

				if (_tab != null)
				{
					_tab.Dispose();
					_tab = null;
				}

				if (_autoHideTab != null)
				{
					_autoHideTab.Dispose();
					_autoHideTab = null;
				}

				_dockPanel = value;

				if (_dockPanel != null)
				{
					_dockPanel.AddContent(Content);
					Form.TopLevel = false;
					Form.FormBorderStyle = FormBorderStyle.None;
					Form.ShowInTaskbar = false;
					Form.WindowState = FormWindowState.Normal;
					NativeMethods.SetWindowPos(Form.Handle, IntPtr.Zero, 0, 0, 0, 0,
						FlagsSetWindowPos.SWP_NOACTIVATE |
						FlagsSetWindowPos.SWP_NOMOVE |
						FlagsSetWindowPos.SWP_NOSIZE |
						FlagsSetWindowPos.SWP_NOZORDER |
						FlagsSetWindowPos.SWP_NOOWNERZORDER |
						FlagsSetWindowPos.SWP_FRAMECHANGED);
				}
			}
		} DockPanel _dockPanel = null;

		/// <summary>
		/// Form Icon
		/// </summary>
		public Icon Icon
		{
			get { return Form.Icon; }
		}

		/// <summary>
		/// Dock Pane
		/// </summary>
		public DockPane Pane
		{
			get { return IsFloat ? FloatPane : PanelPane; }
			set
			{
				if (Pane == value)
					return;

				DockPanel.SuspendLayout(true);

				DockPane oldPane = Pane;

				SuspendSetDockState();
				FloatPane = (value == null ? null : (value.IsFloat ? value : FloatPane));
				PanelPane = (value == null ? null : (value.IsFloat ? PanelPane : value));
				ResumeSetDockState(IsHidden, value != null ? value.DockState : DockState.Unknown, oldPane);

				DockPanel.ResumeLayout(true, true);
			}
		}

		/// <summary>
		/// IsHidden
		/// </summary>
		public bool IsHidden
		{
			get { return _isHidden; }
			set
			{
				if (_isHidden == value)
					return;

				SetDockState(value, VisibleState, Pane);
			}
		} bool _isHidden = true;

		/// <summary>
		/// Tab Text
		/// </summary>
		public string TabText
		{
			get { return _tabText == null ? Form.Text : _tabText; }
			set
			{
				if (_tabText == value)
					return;

				_tabText = value;
				if (Pane != null)
					Pane.RefreshChanges();
			}
		} string _tabText = null;

		/// <summary>
		/// VisibleState
		/// </summary>
		public DockState VisibleState
		{
			get { return _visibleState; }
			set
			{
				if (_visibleState == value)
					return;

				SetDockState(IsHidden, value, Pane);
			}
		} DockState _visibleState = DockState.Unknown;

		/// <summary>
		/// IsFloat
		/// </summary>
		public bool IsFloat
		{
			get { return _isFloat; }
			set
			{
				if (_isFloat == value)
					return;

				DockState visibleState = CheckDockState(value);

				if (visibleState == DockState.Unknown)
					throw new InvalidOperationException(Strings.DockContentHandler_IsFloat_InvalidValue);

				SetDockState(IsHidden, visibleState, Pane);
			}
		} bool _isFloat = false;

		/// <summary>
		/// CheckDockState
		/// </summary>
		/// <param name="isFloat">Should float</param>
		/// <returns>DockState</returns>
		[SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters")]
		public DockState CheckDockState(bool isFloat)
		{
			DockState dockState;

			if (isFloat)
			{
				if (!IsDockStateValid(DockState.Float))
					dockState = DockState.Unknown;
				else
					dockState = DockState.Float;
			}
			else
				dockState = (PanelPane != null) ? PanelPane.DockState : DefaultDockState;

			return dockState;
		}

		/// <summary>
		/// PanelPane
		/// </summary>
		public DockPane PanelPane
		{
			get { return _panelPane; }
			set
			{
				if (_panelPane == value)
					return;

				if (value != null)
				{
					if (value.IsFloat || value.DockPanel != DockPanel)
						throw new InvalidOperationException(Strings.DockContentHandler_DockPane_InvalidValue);
				}

				DockPane oldPane = Pane;

				if (_panelPane != null)
					RemoveFromPane(_panelPane);
				_panelPane = value;
				if (_panelPane != null)
				{
					_panelPane.AddContent(Content);
					SetDockState(IsHidden, IsFloat ? DockState.Float : _panelPane.DockState, oldPane);
				}
				else
					SetDockState(IsHidden, DockState.Unknown, oldPane);
			}
		} DockPane _panelPane = null;

		/// <summary>
		/// ContextMenuStrip
		/// </summary>
		public ContextMenuStrip TabPageContextMenuStrip
		{
			get { return _tabPageContextMenuStrip; }
			set { _tabPageContextMenuStrip = value; }
		} ContextMenuStrip _tabPageContextMenuStrip = null;

		/// <summary>
		/// FloatPane
		/// </summary>
		public DockPane FloatPane
		{
			get { return _floatPane; }
			set
			{
				if (_floatPane == value)
					return;

				if (value != null)
				{
					if (!value.IsFloat || value.DockPanel != DockPanel)
						throw new InvalidOperationException(Strings.DockContentHandler_FloatPane_InvalidValue);
				}

				DockPane oldPane = Pane;

				if (_floatPane != null)
					RemoveFromPane(_floatPane);
				_floatPane = value;
				if (_floatPane != null)
				{
					_floatPane.AddContent(Content);
					SetDockState(IsHidden, IsFloat ? DockState.Float : VisibleState, oldPane);
				}
				else
					SetDockState(IsHidden, DockState.Unknown, oldPane);
			}
		} DockPane _floatPane = null;

		/// <summary>
		/// GetPersistStringCallback
		/// </summary>
		public GetPersistStringCallback GetPersistStringCallback
		{
			get { return _getPersistStringCallback; }
			set { _getPersistStringCallback = value; }
		} GetPersistStringCallback _getPersistStringCallback = null;

		/// <summary>
		/// Hide On Close
		/// </summary>
		public bool HideOnClose
		{
			get { return _hideOnClose; }
			set { _hideOnClose = value; }
		} bool _hideOnClose = false;

		/// <summary>
		/// Show DockState Hint
		/// </summary>
		public DockState ShowHint
		{
			get { return _showHint; }
			set
			{
				if (!DockHelper.IsDockStateValid(value, DockAreas))
					throw (new InvalidOperationException(Strings.DockContentHandler_ShowHint_InvalidValue));

				if (_showHint == value)
					return;

				_showHint = value;
			}
		} DockState _showHint = DockState.Unknown;

		/// <summary>
		/// Is Activated
		/// </summary>
		public bool IsActivated
		{
			get { return _isActivated; }
			internal set
			{
				if (_isActivated == value)
					return;

				_isActivated = value;
			}
		} bool _isActivated = false;

		/// <summary>
		/// IsDockStateValid
		/// </summary>
		/// <param name="dockState">DockState</param>
		/// <returns>Match</returns>
		public bool IsDockStateValid(DockState dockState)
		{
			if (DockPanel != null && dockState == DockState.Document && DockPanel.DocumentStyle == DocumentStyle.SystemMdi)
				return false;
			else
				return DockHelper.IsDockStateValid(dockState, DockAreas);
		}

		/// <summary>
		/// TabPage ContextMenu
		/// </summary>
		public ContextMenu TabPageContextMenu
		{
			get { return _tabPageContextMenu; }
			set { _tabPageContextMenu = value; }
		} ContextMenu _tabPageContextMenu = null;

		/// <summary>
		/// ToolTipText
		/// </summary>
		public string ToolTipText
		{
			get { return _toolTipText; }
			set { _toolTipText = value; }
		} string _toolTipText = null;

		/// <summary>
		/// ActiveWindowHandle
		/// </summary>
		internal IntPtr ActiveWindowHandle
		{
			get { return _activeWindowHandle; }
			set { _activeWindowHandle = value; }
		} IntPtr _activeWindowHandle = IntPtr.Zero;

		private DockState DefaultDockState
		{
			get
			{
				if (ShowHint != DockState.Unknown && ShowHint != DockState.Hidden)
					return ShowHint;

				if ((DockAreas & DockAreas.Document) != 0)
					return DockState.Document;
				if ((DockAreas & DockAreas.DockRight) != 0)
					return DockState.DockRight;
				if ((DockAreas & DockAreas.DockLeft) != 0)
					return DockState.DockLeft;
				if ((DockAreas & DockAreas.DockBottom) != 0)
					return DockState.DockBottom;
				if ((DockAreas & DockAreas.DockTop) != 0)
					return DockState.DockTop;

				return DockState.Unknown;
			}
		}

		private DockState DefaultShowState
		{
			get
			{
				if (ShowHint != DockState.Unknown)
					return ShowHint;

				if ((DockAreas & DockAreas.Document) != 0)
					return DockState.Document;
				if ((DockAreas & DockAreas.DockRight) != 0)
					return DockState.DockRight;
				if ((DockAreas & DockAreas.DockLeft) != 0)
					return DockState.DockLeft;
				if ((DockAreas & DockAreas.DockBottom) != 0)
					return DockState.DockBottom;
				if ((DockAreas & DockAreas.DockTop) != 0)
					return DockState.DockTop;
				if ((DockAreas & DockAreas.Float) != 0)
					return DockState.Float;

				return DockState.Unknown;
			}
		}

		private EventHandlerList Events
		{
			get { return _events; }
		} EventHandlerList _events;

		private void RemoveFromPane(DockPane pane)
		{
			pane.RemoveContent(Content);
			SetPane(null);
			if (pane.Contents.Count == 0)
				pane.Dispose();
		}

		private void SuspendSetDockState()
		{
			_countSetDockState++;
		} int _countSetDockState = 0;

		private void ResumeSetDockState()
		{
			_countSetDockState--;
			if (_countSetDockState < 0)
				_countSetDockState = 0;
		}

		internal bool IsSuspendSetDockState
		{
			get { return _countSetDockState != 0; }
		}

		private void ResumeSetDockState(bool isHidden, DockState visibleState, DockPane oldPane)
		{
			ResumeSetDockState();
			SetDockState(isHidden, visibleState, oldPane);
		}

		internal void SetDockState(bool isHidden, DockState visibleState, DockPane oldPane)
		{
			if (IsSuspendSetDockState)
				return;

			if (DockPanel == null && visibleState != DockState.Unknown)
				throw new InvalidOperationException(Strings.DockContentHandler_SetDockState_NullPanel);

			if (visibleState == DockState.Hidden || (visibleState != DockState.Unknown && !IsDockStateValid(visibleState)))
				throw new InvalidOperationException(Strings.DockContentHandler_SetDockState_InvalidState);

			DockPanel dockPanel = DockPanel;
			if (dockPanel != null)
				dockPanel.SuspendLayout(true);

			SuspendSetDockState();

			DockState oldDockState = DockState;

			if (_isHidden != isHidden || oldDockState == DockState.Unknown)
				_isHidden = isHidden;
			
			_visibleState = visibleState;
			_dockState = isHidden ? DockState.Hidden : visibleState;

			if (visibleState == DockState.Unknown)
				Pane = null;
			else
			{
				_isFloat = (_visibleState == DockState.Float);

				if (Pane == null)
					Pane = DockPanel.DockPaneFactory.CreateDockPane(Content, visibleState, true);
				else if (Pane.DockState != visibleState)
				{
					if (Pane.Contents.Count == 1)
						Pane.SetDockState(visibleState);
					else
						Pane = DockPanel.DockPaneFactory.CreateDockPane(Content, visibleState, true);
				}
			}

			if (Form.ContainsFocus)
				if (DockState == DockState.Hidden || DockState == DockState.Unknown)
					DockPanel.ContentFocusManager.GiveUpFocus(Content);

			SetPaneAndVisible(Pane);

			if (oldPane != null && !oldPane.IsDisposed && oldDockState == oldPane.DockState)
				RefreshDockPane(oldPane);

			if (Pane != null && DockState == Pane.DockState)
			{
				if ((Pane != oldPane) ||
					(Pane == oldPane && oldDockState != oldPane.DockState))
					RefreshDockPane(Pane);
			}

			if (oldDockState != DockState)
			{
				if (DockState == DockState.Hidden || DockState == DockState.Unknown ||
					DockHelper.IsDockStateAutoHide(DockState))
					DockPanel.ContentFocusManager.RemoveFromList(Content);
				else
					DockPanel.ContentFocusManager.AddToList(Content);

				OnDockStateChanged(EventArgs.Empty);
			}

			ResumeSetDockState();

			if (dockPanel != null)
				dockPanel.ResumeLayout(true, true);
		}

		private static void RefreshDockPane(DockPane pane)
		{
			pane.RefreshChanges();
			pane.ValidateActiveContent();
		}

		internal string PersistString
		{
			get { return GetPersistStringCallback == null ? Form.GetType().ToString() : GetPersistStringCallback(); }
		}


		/// <summary>
		/// Activate
		/// </summary>
		public void Activate()
		{
			if (DockPanel == null)
				Form.Activate();
			else if (Pane == null)
				Show(DockPanel);
			else
			{
				IsHidden = false;
				Pane.ActiveContent = Content;
				if (DockState == DockState.Document && DockPanel.DocumentStyle == DocumentStyle.SystemMdi)
				{
					Form.Activate();
					return;
				}
				else if (DockHelper.IsDockStateAutoHide(DockState))
					DockPanel.ActiveAutoHideContent = Content;

				if (!Form.ContainsFocus)
					DockPanel.ContentFocusManager.Activate(Content);
			}
		}

		/// <summary>
		/// GiveUpFocus
		/// </summary>
		public void GiveUpFocus()
		{
			DockPanel.ContentFocusManager.GiveUpFocus(Content);
		}

		/// <summary>
		/// Hide
		/// </summary>
		public void Hide()
		{
			IsHidden = true;
		}

		/// <summary>
		/// Show
		/// </summary>
		public void Show()
		{
			if (DockPanel == null)
				Form.Show();
			else
				Show(DockPanel);
		}

		/// <summary>
		/// Show
		/// </summary>
		/// <param name="dockPanel">Owning DockPanel</param>
		public void Show(DockPanel dockPanel)
		{
			if (dockPanel == null)
				throw (new ArgumentNullException(Strings.DockContentHandler_Show_NullDockPanel));

			if (DockState == DockState.Unknown)
				Show(dockPanel, DefaultShowState);
			else
				Activate();
		}

		/// <summary>
		/// Show DockPanel
		/// </summary>
		/// <param name="dockPanel">Desired DockPanel</param>
		/// <param name="dockState">Desired DockState</param>
		public void Show(DockPanel dockPanel, DockState dockState)
		{
			if (dockPanel == null)
				throw (new ArgumentNullException(Strings.DockContentHandler_Show_NullDockPanel));

			if (dockState == DockState.Unknown || dockState == DockState.Hidden)
				throw (new ArgumentException(Strings.DockContentHandler_Show_InvalidDockState));

			dockPanel.SuspendLayout(true);

			DockPanel = dockPanel;

			if (dockState == DockState.Float && FloatPane == null)
				Pane = DockPanel.DockPaneFactory.CreateDockPane(Content, DockState.Float, true);
			else if (PanelPane == null)
			{
				DockPane paneExisting = null;
				foreach (DockPane pane in DockPanel.Panes)
					if (pane.DockState == dockState)
					{
						paneExisting = pane;
						break;
					}

				if (paneExisting == null)
					Pane = DockPanel.DockPaneFactory.CreateDockPane(Content, dockState, true);
				else
					Pane = paneExisting;
			}

			DockState = dockState;
			Activate();

			dockPanel.ResumeLayout(true, true);
		}

		/// <summary>
		/// Show DockPanel
		/// </summary>
		/// <param name="dockPanel">Desired DockPanel</param>
		/// <param name="floatWindowBounds">Desired Rectangle</param>
		[SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters")]
		public void Show(DockPanel dockPanel, Rectangle floatWindowBounds)
		{
			if (dockPanel == null)
				throw (new ArgumentNullException(Strings.DockContentHandler_Show_NullDockPanel));

			dockPanel.SuspendLayout(true);

			DockPanel = dockPanel;
			if (FloatPane == null)
			{
				IsHidden = true;	// to reduce the screen flicker
				FloatPane = DockPanel.DockPaneFactory.CreateDockPane(Content, DockState.Float, false);
				FloatPane.FloatWindow.StartPosition = FormStartPosition.Manual;
			}

			FloatPane.FloatWindow.Bounds = floatWindowBounds;

			Show(dockPanel, DockState.Float);
			Activate();

			dockPanel.ResumeLayout(true, true);
		}

		/// <summary>
		/// Show DockPanel
		/// </summary>
		/// <param name="pane">Desired DockPane</param>
		/// <param name="beforeContent">In front of</param>
		public void Show(DockPane pane, IDockContent beforeContent)
		{
			if (pane == null)
				throw (new ArgumentNullException(Strings.DockContentHandler_Show_NullPane));

			if (beforeContent != null && pane.Contents.IndexOf(beforeContent) == -1)
				throw (new ArgumentException(Strings.DockContentHandler_Show_InvalidBeforeContent));

			pane.DockPanel.SuspendLayout(true);

			DockPanel = pane.DockPanel;
			Pane = pane;
			pane.SetContentIndex(Content, pane.Contents.IndexOf(beforeContent));
			Show();

			pane.DockPanel.ResumeLayout(true, true);
		}

		/// <summary>
		/// Show DockPanel
		/// </summary>
		/// <param name="previousPane">Previous DockPane</param>
		/// <param name="alignment">DockAlignment</param>
		/// <param name="proportion">The Proportion</param>
		public void Show(DockPane previousPane, DockAlignment alignment, double proportion)
		{
			if (previousPane == null)
				throw (new ArgumentException(Strings.DockContentHandler_Show_InvalidPrevPane));

			if (DockHelper.IsDockStateAutoHide(previousPane.DockState))
				throw (new ArgumentException(Strings.DockContentHandler_Show_InvalidPrevPane));

			previousPane.DockPanel.SuspendLayout(true);

			DockPanel = previousPane.DockPanel;
			DockPanel.DockPaneFactory.CreateDockPane(Content, previousPane, alignment, proportion, true);
			Show();

			previousPane.DockPanel.ResumeLayout(true, true);
		}

		/// <summary>
		/// Close the Form
		/// </summary>
		public void Close()
		{
			DockPanel dockPanel = DockPanel;
			if (dockPanel != null)
				dockPanel.SuspendLayout(true);
			Form.Close();
			if (dockPanel != null)
				dockPanel.ResumeLayout(true, true);

		}


		private void SetParent(Control value)
		{
			if (Form.Parent == value)
				return;

			//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
			// Workaround of .Net Framework bug:
			// Change the parent of a control with focus may result in the first
			// MDI child form get activated. 
			//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
			bool bRestoreFocus = false;
			if (Form.ContainsFocus)
			{
				if (value == null)
					DockPanel.ContentFocusManager.GiveUpFocus(this.Content);
				else
				{
					DockPanel.SaveFocus();
					bRestoreFocus = true;
				}
			}
			//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

			Form.Parent = value;

			//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
			// Workaround of .Net Framework bug:
			// Change the parent of a control with focus may result in the first
			// MDI child form get activated. 
			//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
			if (bRestoreFocus)
				Activate();
			//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		}

		private void SetPane(DockPane pane)
		{
			if (pane != null && pane.DockState == DockState.Document && DockPanel.DocumentStyle == DocumentStyle.DockingMdi)
			{
				if (Form.Parent is DockPane)
					SetParent(null);
				if (Form.MdiParent != DockPanel.ParentForm)
				{
					FlagClipWindow = true;
					Form.MdiParent = DockPanel.ParentForm;
				}
			}
			else
			{
				FlagClipWindow = true;
				if (Form.MdiParent != null)
					Form.MdiParent = null;
				if (Form.TopLevel)
					Form.TopLevel = false;
				SetParent(pane);
			}
		}

		private void For_Disposed(object sender, EventArgs e)
		{
			Dispose();
		}

		private void For_TextChanged(object sender, EventArgs e)
		{
			if (DockHelper.IsDockStateAutoHide(DockState))
				DockPanel.RefreshAutoHideStrip();
			else if (Pane != null)
			{
				if (Pane.FloatWindow != null)
					Pane.FloatWindow.SetText();
				Pane.RefreshChanges();
			}
		}

		internal void SetPaneAndVisible(DockPane pane)
		{
			SetPane(pane);
			SetVisible();
		}

		internal void SetVisible()
		{
			bool visible;

			if (IsHidden)
				visible = false;
			else if (Pane != null && Pane.DockState == DockState.Document && DockPanel.DocumentStyle == DocumentStyle.DockingMdi)
				visible = true;
			else if (Pane != null && Pane.ActiveContent == Content)
				visible = true;
			else if (Pane != null && Pane.ActiveContent != Content)
				visible = false;
			else
				visible = Form.Visible;

			if (Form.Visible != visible)
				Form.Visible = visible;
		}

		internal DockPaneStripBase.Tab GetTab(DockPaneStripBase dockPaneStrip)
		{
			if (_tab == null)
				_tab = dockPaneStrip.CreateTab(Content);

			return _tab;
		} DockPaneStripBase.Tab _tab = null;

		internal IDisposable AutoHideTab
		{
			get { return _autoHideTab; }
			set { _autoHideTab = value; }
		} IDisposable _autoHideTab = null;

		internal bool FlagClipWindow
		{
			get { return _flagClipWindow; }
			set
			{
				if (_flagClipWindow == value)
					return;

				_flagClipWindow = value;
				if (_flagClipWindow)
					Form.Region = new Region(Rectangle.Empty);
				else
					Form.Region = null;
			}
		} bool _flagClipWindow = false;

		#region IDockDragSource Members

		Control IDragSource.DragControl
		{
			get { return Form; }
		}

		bool IDockDragSource.CanDockTo(DockPane pane)
		{
			if (!IsDockStateValid(pane.DockState))
				return false;

			if (Pane == pane && pane.DisplayingContents.Count == 1)
				return false;

			return true;
		}
		/// <summary>
		/// BeginDrag
		/// </summary>
		/// <param name="ptMouse">Point</param>
		/// <returns></returns>
		Rectangle IDockDragSource.BeginDrag(Point ptMouse)
		{
			Size size;
			DockPane floatPane = this.FloatPane;
			if (DockState == DockState.Float || floatPane == null || floatPane.FloatWindow.NestedPanes.Count != 1)
				size = DockPanel.DefaultFloatWindowSize;
			else
				size = floatPane.FloatWindow.Size;

			Point location;
			Rectangle rectPane = Pane.ClientRectangle;
			if (DockState == DockState.Document)
				location = new Point(rectPane.Left, rectPane.Top);
			else
			{
				location = new Point(rectPane.Left, rectPane.Bottom);
				location.Y -= size.Height;
			}
			location = Pane.PointToScreen(location);

			if (ptMouse.X > location.X + size.Width)
				location.X += ptMouse.X - (location.X + size.Width) + Measures.SplitterSize;

			return new Rectangle(location, size);
		}

		/// <summary>
		/// FloatAt
		/// </summary>
		/// <param name="floatWindowBounds">Rectangle</param>
		public void FloatAt(Rectangle floatWindowBounds)
		{
			DockPane pane = DockPanel.DockPaneFactory.CreateDockPane(Content, floatWindowBounds, true);
		}
		/// <summary>
		/// DockTo
		/// </summary>
		/// <param name="pane">DockPane</param>
		/// <param name="dockStyle">DockStyle</param>
		/// <param name="contentIndex">int</param>
		public void DockTo(DockPane pane, DockStyle dockStyle, int contentIndex)
		{
			if (dockStyle == DockStyle.Fill)
			{
				bool samePane = (Pane == pane);
				if (!samePane)
					Pane = pane;

				if (contentIndex == -1 || !samePane)
					pane.SetContentIndex(Content, contentIndex);
				else
				{
					DockContentCollection contents = pane.Contents;
					int oldIndex = contents.IndexOf(Content);
					int newIndex = contentIndex;
					if (oldIndex < newIndex)
					{
						newIndex += 1;
						if (newIndex > contents.Count - 1)
							newIndex = -1;
					}
					pane.SetContentIndex(Content, newIndex);
				}
			}
			else
			{
				DockPane paneFrom = DockPanel.DockPaneFactory.CreateDockPane(Content, pane.DockState, true);
				INestedPanesContainer container = pane.NestedPanesContainer;
				if (dockStyle == DockStyle.Left)
					paneFrom.DockTo(container, pane, DockAlignment.Left, 0.5);
				else if (dockStyle == DockStyle.Right)
					paneFrom.DockTo(container, pane, DockAlignment.Right, 0.5);
				else if (dockStyle == DockStyle.Top)
					paneFrom.DockTo(container, pane, DockAlignment.Top, 0.5);
				else if (dockStyle == DockStyle.Bottom)
					paneFrom.DockTo(container, pane, DockAlignment.Bottom, 0.5);

				paneFrom.DockState = pane.DockState;
			}
		}
		/// <summary>
		/// DockTo
		/// </summary>
		/// <param name="panel">DockPanel</param>
		/// <param name="dockStyle">DockStyle</param>
		public void DockTo(DockPanel panel, DockStyle dockStyle)
		{
			if (panel != DockPanel)
				throw new ArgumentException(Strings.IDockDragSource_DockTo_InvalidPanel, "panel");

			DockPane pane;

			if (dockStyle == DockStyle.Top)
				pane = DockPanel.DockPaneFactory.CreateDockPane(Content, DockState.DockTop, true);
			else if (dockStyle == DockStyle.Bottom)
				pane = DockPanel.DockPaneFactory.CreateDockPane(Content, DockState.DockBottom, true);
			else if (dockStyle == DockStyle.Left)
				pane = DockPanel.DockPaneFactory.CreateDockPane(Content, DockState.DockLeft, true);
			else if (dockStyle == DockStyle.Right)
				pane = DockPanel.DockPaneFactory.CreateDockPane(Content, DockState.DockRight, true);
			else if (dockStyle == DockStyle.Fill)
				pane = DockPanel.DockPaneFactory.CreateDockPane(Content, DockState.Document, true);
			else
				return;
		}

		#endregion
	}
}